package com.logic.landseaserver.service.impl;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;

import com.logic.landseaserver.domain.*;
import com.logic.landseaserver.persistence.write.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.logic.common.exception.BusinessException;
import com.logic.common.security.SecurityUtils;
import com.logic.landseaserver.common.LandeaConstants;
import com.logic.landseaserver.common.LandeaConstants.AccountStatus;
import com.logic.landseaserver.common.LandseaErrorMessageEnum;
import com.logic.landseaserver.common.enums.BillStatusEnum;
import com.logic.landseaserver.common.enums.BillTypeEnum;
import com.logic.landseaserver.common.enums.ContractStatusCodeEnum;
import com.logic.landseaserver.common.enums.RoomStatusCodeEnum;
import com.logic.landseaserver.common.enums.SystemCodeEnum;
import com.logic.landseaserver.common.exception.LandseaException;
import com.logic.landseaserver.common.util.DateUtil;
import com.logic.landseaserver.common.util.LandSeaUtil;
import com.logic.landseaserver.models.authcode.bean.AddCouponUesd;
import com.logic.landseaserver.models.authcode.bean.UsedAuthCode;
import com.logic.landseaserver.models.authcode.service.CouponUsedService;
import com.logic.landseaserver.models.prepayment.bean.AccountResp;
import com.logic.landseaserver.models.prepayment.service.PrepaymentService;
import com.logic.landseaserver.persistence.read.ContractReadMapper;
import com.logic.landseaserver.persistence.read.OffRentReadMapper;
import com.logic.landseaserver.persistence.read.OffrentConfirmReadMapper;
import com.logic.landseaserver.service.IBillService;
import com.logic.landseaserver.service.IContractService;
import com.logic.landseaserver.service.IDdLockService;
import com.logic.landseaserver.service.IOffRent;
import com.logic.landseaserver.service.IOffrentPreBill;
import com.logic.landseaserver.ws.dto.ContractDTO;
import com.logic.landseaserver.ws.dto.ContractPdfDTO;
import com.logic.landseaserver.ws.dto.OffRentContractDTO;
import com.logic.landseaserver.ws.dto.OffRentDTO;
import com.logic.landseaserver.ws.dto.OffrentConfirmDTO;
import com.logic.landseaserver.ws.dto.PreBillDetailDTO;
import com.logic.landseaserver.ws.dto.QueryCouponUesdDTO;
import com.logic.landseaserver.ws.request.AddAuthCodeReq;
import com.logic.landseaserver.ws.response.PreBillResp;
import com.logic.system.domain.SystemFile;
import com.logic.system.service.IConfigurationService;
import com.logic.system.service.IFileService;
import com.logic.system.service.impl.ConfigurationService;


/**
 *
 * 项目名称：system-server</br>
 * 类名称：OffRentServiceImpl</br>
 * 类描述：</br>
 * 创建人：tony</br>
 * 创建时间：2017年8月14日 下午4:27:12</br>
 * 
 * @version 1.0
 *         
 */

@Service
public class OffRentServiceImpl implements IOffRent
{
    @Autowired
    private OffRentWriteMapper offRentWriteMapper;
    
    @Autowired
    private OffRentReadMapper offRentReadMapper;
    
    @Autowired
    private ContractReadMapper contractReadMapper;

    @Autowired
    private ContractWriteMapper contractWriteMapper;
    
    @Autowired
    private RoomWriteMapper roomWriteMapper;

    @Autowired
    private IContractService contractService;

    @Autowired
    private IOffrentPreBill offrentPreBillService;

    @Autowired
    private IBillService billService;
    
    @Autowired
    private IFileService fileService;
    
    @Autowired
    private OffrentConfirmWriteMapper offrentConfirmWriteMapper;
    
    @Autowired
    private OffrentConfirmReadMapper offrentConfirmReadMapper;

    @Autowired
    private CheckFeeListWriteMapper checkFeeListWriteMapper;

    @Autowired
    private CheckListWriteMapper checkListWriteMapper;

    @Autowired
    private IDdLockService ddLockService;

    @Autowired
    private IConfigurationService configurationService;

    @Autowired
    private MonthlyBillWriteMapper monthlyBillWriteMapper;

    @Autowired
    private CouponUsedService couponUsedService;

    @Autowired
    private PreOffrentDetailBillWriteMapper preOffrentDetailBillWriteMapper;

    @Autowired
    private PreOffrentBillWriteMapper preOffrentBillWriteMapper;
    
    @Autowired
    private PrepaymentService prepaymentService;

    @Autowired
    private CouponWriteMapper couponWriteMapper;

    private static final Logger log = LoggerFactory.getLogger(OffRentServiceImpl.class);
    /**
     * 
     * [描述]：必须加事务</br>
     *
     * @param offRent
     * @return
     * @throws LandseaException
     *
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {LandseaException.class, Exception.class})
    public HashMap<String,Object> addOrEditOffrent(OffRent offRent)
        throws LandseaException{
        
        validateDate(offRent);
        Integer contractId = offRent.getContractId();
        ContractDTO contract = contractReadMapper.queryContractDetail(contractId);
        if(contract==null){
            throw LandseaException.createException(LandseaErrorMessageEnum.CONTRACT_IS_NULL); 
        }
        Integer roomId = contract.getRoomId();
        if(roomId == null){
            throw LandseaException.createException(LandseaErrorMessageEnum.ROOM_IS_NULL); 
        }
        
        //往房间添加退租标签
        if(offRent.getOffrentType().equals(LandeaConstants.ReRentType.OFFRENT)){
            Room room = new Room();
            room.setId(roomId);
            room.setOffrentStatus(true);
            roomWriteMapper.updateByPrimaryKeySelective(room);
        }
       // offRent.setOffrentType(LandeaConstants.ReRentType.OFFRENT);
        offRent.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
        HashMap<String,Object> result = new HashMap<String,Object>();
        if (exiteOffRent(contractId)){ // 存在 --- 更新
            String certificateName = contract.getCertificatesName();
            if(offRent.getCardUserName().equals(certificateName)){
                offRent.setFileId(null);
            }
            offRentWriteMapper.updateByContractIdSelective(offRent);
        }else{ // 不存在 -- 插入
            offRentWriteMapper.insertSelective(offRent);
        }
        result.put("status", 0);
        return result;
    }

    @Override
    public OffRentContractDTO getOffRent(Integer contractId,String offrentType) throws LandseaException, BusinessException{
        OffRentContractDTO offRentDTO = new OffRentContractDTO();
        HashMap queryMap = new HashMap();
        queryMap.put("contractId",contractId);
        //queryMap.put("offrentType",offrentType);
        List<OffRentDTO> offRent = offRentReadMapper.selectByCondt(queryMap);
        ContractPdfDTO obj = null;
        try{
            obj = contractService.getContractPdfDTO(contractId);
        }
        catch (Exception e){
            e.printStackTrace();
        }
        offRentDTO.setContract(obj);
        if (offRent.size() > 1){
            throw LandseaException.createException(LandseaErrorMessageEnum.CONTRACTID_HAVE_MULTI_OFFRENT);
        }else if (offRent.size() == 0){
            
        }else{
            OffRentDTO terr = offRent.get(0);
            String fileId = terr.getFileId();
            if(null!=fileId){
                SystemFile file = (SystemFile)fileService.get(fileId);
                if(null!=file){
                    offRentDTO.setSystemFile(file);
                }
            }
            offRentDTO.setOffRent(terr);
        }
        return offRentDTO;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {LandseaException.class, Exception.class})
    public HashMap<String, Object> cancelApplyByContractId(Integer contractId) throws LandseaException{
        cancelApply(contractId);
        HashMap<String,Object> result = new HashMap<String,Object>();
        result.put("status", 0);
        return result;
    }

    public void cancelApply(Integer contractId) throws LandseaException {
        Contract contract = contractReadMapper.selectByPrimaryKey(contractId);
        if(contract==null){
            throw LandseaException.createException(LandseaErrorMessageEnum.CONTRACT_IS_NULL);
        }
        //合同状态只能为已签约
        if(!contract.getStatus().equals(ContractStatusCodeEnum.SIGN.getCode())){
            throw LandseaException.createException(LandseaErrorMessageEnum.CONTRACT_STATUS_IS_ERROR_OFFRENTBILL);
        }
        Integer roomId = contract.getRoomId();
        if(roomId == null){
            throw LandseaException.createException(LandseaErrorMessageEnum.ROOM_IS_NULL);
        }
        Room room = new Room();
        room.setId(roomId);
        room.setOffrentStatus(false);
        roomWriteMapper.updateByPrimaryKeySelective(room);
        offRentWriteMapper.deleteByContractId(contractId);
        
        // 更新账户为正常
        prepaymentService.updateAccountStatusByRoomAndUser(roomId, contract.getUserId(), AccountStatus.NORMAL);
        log.info("已更新账户roomId=" + roomId + ",userId=" + contract.getUserId() + "的账户状态为：正常.");
    }


    private void validateDate(OffRent offRent) throws LandseaException{
        if(null==offRent.getContractId()){
            throw LandseaException.createException(LandseaErrorMessageEnum.CONTRACTID_IS_NULL); 
        }
        if(null==offRent.getApplyDate()){
            throw LandseaException.createException(LandseaErrorMessageEnum.APPLYDATE_IS_NULL); 
        }
/*        if(StringUtils.isEmpty(offRent.getCardUserName())){
            throw LandseaException.createException(LandseaErrorMessageEnum.CARDUERNAME_IS_NULL); 
        }*/
        if(StringUtils.isEmpty(offRent.getOffrentReason())){
            throw LandseaException.createException(LandseaErrorMessageEnum.OFFRENTREASON_IS_NULL); 
        }
        if(StringUtils.isEmpty(offRent.getOriginated())){
            throw LandseaException.createException(LandseaErrorMessageEnum.ORIGINATE_IS_NULL); 
        }
        if(StringUtils.isEmpty(offRent.getOffrentType())){
            throw LandseaException.createException(LandseaErrorMessageEnum.OFFRENTTYPE_IS_NULL);
        }
        if(SystemCodeEnum.ORTHERREASON.getCode().equals(offRent.getOffrentReason())){
            if(StringUtils.isEmpty(offRent.getOffrentReason())){
                throw LandseaException.createException(LandseaErrorMessageEnum.OFFRENTORTHERREASON_IS_NULL); 
            }
        }
    }
    
    
    private boolean exiteOffRent(Integer contractId)
        throws LandseaException{
        HashMap queryMap = new HashMap();
        queryMap.put("contractId",contractId);
      //  queryMap.put("offrentType",LandeaConstants.ReRentType.OFFRENT);
        List<OffRentDTO> offrent = offRentReadMapper.selectByCondt(queryMap);
        if (offrent.size() > 1){
            throw LandseaException.createException(LandseaErrorMessageEnum.CONTRACTID_HAVE_MULTI_OFFRENT);
        }
        else if (offrent.size() == 0){
            return false;
        }
        else{
            return true;
        }
    }


    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {LandseaException.class, Exception.class})
    public void addPreBill(Integer contractId) throws LandseaException {
        //查询该合同是否存在
        Contract contract = contractReadMapper.selectByPrimaryKey(contractId);
        if (contract == null) {
            throw LandseaException.createException(LandseaErrorMessageEnum.CONTRACT_IS_NULL);
        }
        offrentPreBillService.addPreBill(contract, true);
        //修改退租申请实际退租日期
        OffRent updateRent = new OffRent();
        updateRent.setContractId(contractId);
        updateRent.setOffrentDate(new Date());
        updateRent.setLastModifiedDtm(new Timestamp((new Date()).getTime()));
        updateRent.setLastModifiedBy(SecurityUtils.getCurrentLogin().getUserId());
        offRentWriteMapper.updateByContractIdSelective(updateRent);
    }

    @Override
    public Object queryPreBill(Integer contractId,String billType) throws LandseaException {
        PreBillResp resp = new PreBillResp();
        //查询该合同是否存在
        Contract contract = contractReadMapper.selectByPrimaryKey(contractId);
        if (contract == null) {
            throw LandseaException.createException(LandseaErrorMessageEnum.CONTRACT_IS_NULL);
        }
        PreOffrentBill preBill= offrentPreBillService.queryPreBillByContractId(contractId);
        if(preBill==null){
            throw LandseaException.createException(LandseaErrorMessageEnum.OFFRENT_PRE_BILL_ERROR);
        }
        resp = PreBillResp.convertResp(preBill);
        List<PreBillDetailDTO> positives= new ArrayList<>();
        List<PreBillDetailDTO> nagatives = new ArrayList<>();
        Double positiveAmount= 0.0;
        Double nagativeAmount=0.0;
        List<PreOffrentDetailBill> details = offrentPreBillService.queryPreBillDetailByPreId(preBill.getId(),billType);
        if(details!=null){
            for(PreOffrentDetailBill detail : details){
                PreBillDetailDTO pdDto = PreBillDetailDTO.convertPojoToDto(detail);
                Double amount =pdDto.getBillAmount();
                if(amount<0){
                    nagatives.add(pdDto);
                    nagativeAmount = nagativeAmount +amount;
                }else {
                    positives.add(pdDto);
                    positiveAmount = positiveAmount +amount;
                }
            }
            List<BillDetail> lastPayBillDts =offrentPreBillService.queryLastPayBill(contractId);
            if(lastPayBillDts!=null){
                Optional<BillDetail> hourseDpsBill = lastPayBillDts.stream().filter(e -> e.getType().equals(BillTypeEnum.CTBI11.getCode())).findFirst();
                if (hourseDpsBill.isPresent()) {
                    resp.setHourseDpsAmount(hourseDpsBill.get().getMoney());
                }
                Optional<BillDetail> hourseBill = lastPayBillDts.stream().filter(e -> e.getType().equals(BillTypeEnum.CTBI8.getCode())).findFirst();
                if (hourseBill.isPresent()) {
                    resp.setLastHourseDate(DateUtil.getInstence().convertDate(hourseBill.get().getDateEnd()));
                }
            }
            resp.setPositiveAmount(LandSeaUtil.get2Double(positiveAmount));
            resp.setNegativeAmount(LandSeaUtil.get2Double(nagativeAmount));
            resp.setRefundAmount(LandSeaUtil.get2Double(positiveAmount+nagativeAmount));
            resp.setNagativeDetails(nagatives);
            resp.setPositiveDetails(positives);
            //TOOD Junny
            // 查询当前账户余额
            AccountResp accountResp = prepaymentService.getAccountTotalMoney(contract.getUserId(), contract.getRoomId());
            if (null != accountResp)
            {
                resp.setUserAccountAmount(accountResp.getMoney());
            }
            else
            {
                resp.setUserAccountAmount(0.0);
            }
            if(billType.equals(LandeaConstants.OffRentBillType.OFFRENTBILL)){
                HashMap queryMap = new HashMap();
                queryMap.put("mainId",preBill.getId());
                queryMap.put("mainType", LandeaConstants.QueryUesdCodeType.OFFRENT);
                List<QueryCouponUesdDTO> uesdCodes = couponUsedService.querypPersonalCouponList(queryMap);
                resp.setUesdCodes(uesdCodes);
            }
        }
        return resp;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {
            LandseaException.class, Exception.class})
    public Contract createOffRentBill(Integer contractId) throws LandseaException {
        //查询该合同是否存在
        Contract contract = contractReadMapper.selectByPrimaryKey(contractId);
        if (contract.getDeleted()) {
            throw LandseaException.createException(LandseaErrorMessageEnum.CONTRACT_IS_NULL);
        }
        if (!contract.getStatus().equals(ContractStatusCodeEnum.SIGN.getCode())) {
            throw LandseaException.createException(LandseaErrorMessageEnum.CONTRACT_STATUS_IS_ERROR);
        }
        PreOffrentBill preBill= offrentPreBillService.queryPreBillByContractId(contractId);
        if(preBill==null){
            throw LandseaException.createException(LandseaErrorMessageEnum.OFFRENT_PRE_BILL_ERROR);
        }
        //查询租客是否确认
        List<PreOffrentDetailBill> details = offrentPreBillService.queryPreBillDetailByPreId(preBill.getId(),LandeaConstants.OffRentBillType.OFFRENTBILL);
        billService.createOffRentBill(preBill,details);
        Integer userId = SecurityUtils.getCurrentLogin().getUserId();
        //释放房源，修改合同状态
        Room room = new Room();
        room.setId(contract.getRoomId());
        room.setDirtyFlag(true);
        room.setSigned(false);
        //如果是转转合同
        if(contract.getRentType()!=null && contract.getRentType().equals(LandeaConstants.ReRentType.CHANGE)){
            //查询是否有当前合同是否有转租合同B 判断是否是正常操作退租还是转租生成退租账单
            ContractDTO changeContract = contractReadMapper.queryReRentContractDetail(contractId);
            if(changeContract!=null){
                room.setDirtyFlag(false);
                room.setSigned(true);
            }
        }
        room.setOffrentStatus(false);
        room.setAppendStatus(RoomStatusCodeEnum.LRB1.getCode());
        room.updateCommonInfo(userId);
        roomWriteMapper.updateByPrimaryKeySelective(room);

        contract.setStatus(ContractStatusCodeEnum.END.getCode());
        //如果是进行换租或者换房
        if(contract.getRentType()!=null){
            if(contract.getRentType().equals(LandeaConstants.ReRentType.CHANGE) || 
                contract.getRentType().equals(LandeaConstants.ReRentType.TURN)){
                contract.setRentStatus(contract.getRentType());
            }
        }
        contract.updateCommonInfo(userId);
        contractWriteMapper.updateByPrimaryKeySelective(contract);
        //删除未支付订单
        billService.deleteNoPay(contractId);
        //删除往期未支付其他费项中的计量类型
        List<String> costAry = new ArrayList<>();
        costAry.add(BillTypeEnum.CTBI1.getCode());
        costAry.add(BillTypeEnum.CTBI2.getCode());
        costAry.add(BillTypeEnum.CTBI3.getCode());
        costAry.add(BillTypeEnum.CTBI4.getCode());

        HashMap cstMap = new HashMap();
        cstMap.put("lastModifiedBy",userId);
        cstMap.put("billMonth",preBill.getBillMonth());
        cstMap.put("costType",costAry.toString());
        cstMap.put("contractId",contractId);
        cstMap.put("billStatus",BillStatusEnum.BIST3.getCode());
        monthlyBillWriteMapper.deleteCostMBillByOffBill(cstMap);
        //门锁密码失效  roomId  失效时间
        int pwdEndTime =Integer.parseInt(configurationService.getStringValue(ConfigurationService.UNRENT_PWD_EXPIRE_TIME));
        ddLockService.resetPasswordEffectiveTime(contract.getRoomId(),contractId, DateUtils.addMinutes(new Date(),pwdEndTime));
        //B合同未入住 A合同直接变成已结束
        String rentType = contract.getRentType()==null ? "" : contract.getRentType();
        boolean rerentFlag = contract.getOriginalCId()!=null && rentType.equals(LandeaConstants.ReRentType.RERENT);
        int reRentInFlag = DateUtil.compareTime(contract.getInDate(),new Date());;
        if(rerentFlag && reRentInFlag>0){
            Contract contractA = new Contract();
            contractA.setId(contract.getOriginalCId());
            contractA.setStatus(ContractStatusCodeEnum.END.getCode());
            contractA.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
            contractWriteMapper.updateByPrimaryKeySelective(contractA);
        }
        //如果有使用授权码，则改变授权码状态为已使用
        for(PreOffrentDetailBill pBill: details){
            if(pBill.getCouponFlag() && pBill.getCouponId()!=null){
                Coupon coupon = new Coupon();
                coupon.setId(pBill.getCouponId());
                coupon.setStatus(LandeaConstants.CouponStatus.USED);
                coupon.setUsedAmount(1);
                coupon.updateCommonInfo(userId);
                couponWriteMapper.updateByPrimaryKeySelective(coupon);
            }
        }
        return contract;
    }

    @Override
    public HashMap<String, Object> uploadOffrentConfirm(OffrentConfirm offrentConfirm) throws LandseaException
    {
        validateOffrentConfirm(offrentConfirm);
        
        boolean exit = exiteOffrentConfirm(offrentConfirm);
        if(exit){
            offrentConfirmWriteMapper.updateByContractIdAndPrebillIdSelective(offrentConfirm);
        }else{
            offrentConfirm.setId(null);
            offrentConfirmWriteMapper.insertSelectiveOffrentConfirm(offrentConfirm);
        }
        
        HashMap<String, Object> result = new HashMap<String, Object>();
        result.put("status", 0);
        return result;
    }

    private boolean exiteOffrentConfirm(OffrentConfirm offrentConfirm)
    {
        OffrentConfirm oc = offrentConfirmReadMapper.selectByContractId(offrentConfirm.getContractId());
        if(null==oc){
            return false;
        }
        return true;
    }

    private void validateOffrentConfirm(OffrentConfirm offrentConfirm) throws LandseaException
    {
        if(null==offrentConfirm.getContractEndDate()){
            offrentConfirm.setContractEndDate(new Date());
        }
        if(null==offrentConfirm.getContractId()){
            throw LandseaException.createException(LandseaErrorMessageEnum.CONTRACTID_IS_NULL);
        }
        if(null==offrentConfirm.getFileId()){
            throw LandseaException.createException(LandseaErrorMessageEnum.FILEID_IS_NULL);
        }
        if(null==offrentConfirm.getPreBillId()){
            throw LandseaException.createException(LandseaErrorMessageEnum.PREBILLID_IS_NULL);
        }
    }

    @Override
    public OffrentConfirmDTO getOffrentConfirm(Integer contractId) throws BusinessException
    {
        OffrentConfirmDTO dto = new OffrentConfirmDTO();
        List<SystemFile> filelist = new ArrayList<SystemFile>();
        OffrentConfirm oc = offrentConfirmReadMapper.selectByContractId(contractId);
        if(null!=oc){
            String fileIds = oc.getFileId(); 
            if(fileIds!=null){
                String[] fileidarray = fileIds.split(",");
                for(String id:fileidarray){
                    SystemFile systemFile = (SystemFile)fileService.get(id);
                    filelist.add(systemFile);
                }
            }
        }
        dto.setOffrentConfirm(oc);
        dto.setFileList(filelist);
        
        return dto; 
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED,  rollbackFor = {LandseaException.class, Exception.class})
    public boolean cancelOffRent(Integer contractId) throws LandseaException {
        boolean result=true;
        //撤销退房申请
        cancelApply(contractId);
        //撤销退房交割单
        checkListWriteMapper.cancelCheckList(contractId, LandeaConstants.CheckType.UN_RENT);
        checkFeeListWriteMapper.cancelCheckFeeList(contractId, LandeaConstants.CheckType.UN_RENT);
        //撤销预结算单
        offrentPreBillService.cancelPreBill(contractId);
        //撤销预结算单的授权码使用记录
        PreOffrentBill preOffrentBill = offrentPreBillService.queryPreBillByContractId(contractId);
        if(preOffrentBill!=null){
            couponUsedService.deleteCouponUesd(preOffrentBill.getId(), LandeaConstants.QueryUesdCodeType.OFFRENT);
        }
        return result;
    }

    @Override
    public void addAuthCode(Object object) throws LandseaException, BusinessException {
        AddAuthCodeReq authCode = (AddAuthCodeReq)object;

        if(authCode.getContractId()==null || authCode.getBillId()==null){
            throw LandseaException.createException(LandseaErrorMessageEnum.AUTHCODE_USED_CIDPID_ERROR);
        }
        Contract contract=contractReadMapper.selectByPrimaryKey(authCode.getContractId());
        if(contract==null){
            throw LandseaException.createException(LandseaErrorMessageEnum.AUTHCODE_USED_CIDPID_ERROR);
        }else{
            if(contract.getDeleted()){
                throw LandseaException.createException(LandseaErrorMessageEnum.AUTHCODE_USED_CIDPID_ERROR);
            }
        }
        PreOffrentBill preBill = offrentPreBillService.queryPreBillByContractId(authCode.getContractId());
        if(preBill==null){
            throw LandseaException.createException(LandseaErrorMessageEnum.AUTHCODE_USED_CIDPID_ERROR);
        }
        //先删除之前用过的授权码
        couponUsedService.removeCouponUesd(preBill.getId(), LandeaConstants.QueryUesdCodeType.OFFRENT);
        //删除账单中的优惠类账单
        preOffrentDetailBillWriteMapper.removeAuthCodeBill(preBill.getId());
        //查询费项
        List<PreOffrentDetailBill> detailBills = offrentPreBillService.queryPreBillDetailByPreId(preBill.getId(),LandeaConstants.OffRentBillType.PREBILL);
        if(detailBills==null){
            throw LandseaException.createException(LandseaErrorMessageEnum.OFFRENT_PRE_BILL_ERROR);
        }
        if(authCode.getAuthCodes().size()!=0){
            //校验是否能使用
            couponUsedService.checkUesdAuthCode(LandeaConstants.QueryUesdCodeType.OFFRENT,contract.getUserId(),authCode.getAuthCodes());
            //新增使用记录
            AddCouponUesd addCodes=new AddCouponUesd();
            addCodes.setUserId(contract.getUserId());
            addCodes.setRoomId(contract.getRoomId());
            addCodes.setAuthCodes(authCode.getAuthCodes());
            addCodes.setPrjId(contract.getProjectId());
            addCodes.setMainId(preBill.getId());
            addCodes.setMainType(LandeaConstants.QueryUesdCodeType.OFFRENT);
            couponUsedService.insertUesdList(addCodes);
            //修改结算单
            List<PreOffrentDetailBill> records = new ArrayList<>();
            //优惠金额
            Double totalAuthAmout = 0.0;
            for(UsedAuthCode usedCode:authCode.getAuthCodes()){
                PreOffrentDetailBill detailBill= new PreOffrentDetailBill();
                detailBill.setPrebillId(preBill.getId());
                detailBill.setPreType(usedCode.getAuthFee());
                Optional<PreOffrentDetailBill> dBill = detailBills.stream().filter(e -> e.getPreType().equals(usedCode.getAuthFee())).findFirst();
                //如果是折扣 则取相对于费项金额进行计算
                Double authAmout = 0.0;
                if(usedCode.getMoneyType().equals(LandeaConstants.MoneyType.DISCOUNT)){
                    if (dBill.isPresent()) {
                        authAmout = LandSeaUtil.get2Double(Math.abs(dBill.get().getBillAmount())*(1-usedCode.getQuota()));
                    }
                }else{
                    authAmout = usedCode.getQuota();
                }
                detailBill.setBillAmount(-authAmout);
                if (dBill.isPresent()) {
                    detailBill.setDateBegin(dBill.get().getDateBegin());
                    detailBill.setDateEnd(dBill.get().getDateEnd());
                }
                detailBill.setCouponFlag(true);
                detailBill.setCouponId(usedCode.getId());
                detailBill.setAuthCode(usedCode.getAuthCode());
                detailBill.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
                records.add(detailBill);
                totalAuthAmout = totalAuthAmout +authAmout;
            }
            preOffrentDetailBillWriteMapper.insertList(records);
            //修改结算单金额
            Double orgPrice = 0.0;
            for(PreOffrentDetailBill bdtail:detailBills){
                orgPrice = orgPrice +bdtail.getBillAmount();
            }
            preBill.setRefundAmount(LandSeaUtil.get2Double(orgPrice-totalAuthAmout));
        }else{
            Double authPrice=0.0;
            for(PreOffrentDetailBill bdtail:detailBills){
                authPrice = authPrice +bdtail.getBillAmount();
            }
            preBill.setRefundAmount(LandSeaUtil.get2Double(authPrice));
        }
        preBill.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
        preOffrentBillWriteMapper.updateByPrimaryKeySelective(preBill);
    }
}

